package cn.jiangzeyin;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 *
 * @author jiangzeyin
 **/
public final class StringUtil {

    private final static String CONFIG_LOCATION_DELIMITERS = ",; \t\n";

    /**
     * GENERAL_PUNCTUATION 判断中文的“号
     * <p>
     * CJK_SYMBOLS_AND_PUNCTUATION 判断中文的。号
     * <p>
     * HALFWIDTH_AND_FULLWIDTH_FORMS 判断中文的，号
     *
     * @param c 字符
     * @return boolean
     * @author jiangzeyin
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS ||
                ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS ||
                ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A ||
                ub == Character.UnicodeBlock.GENERAL_PUNCTUATION ||
                ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION ||
                ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;
    }

    /**
     * 判断是否包含中文
     *
     * @param strName 字符串
     * @return boolean
     * @author jiangzeyin
     */
    public static boolean isChinese(String strName) {
        char[] ch = strName.toCharArray();
        for (char c : ch) {
            if (isChinese(c)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将字符串中的中文替换为其他字符串
     *
     * @param source      原字符串
     * @param replacement 替换后的字符
     * @return 结果
     */
    public static String replaceChinese(String source, String replacement) {
        if (StringUtil.isEmpty(source))
            return "";
        replacement = convertNULL(replacement);
        String reg = "[\u4e00-\u9fa5]";
        Pattern pat = Pattern.compile(reg);
        Matcher mat = pat.matcher(source);
        return mat.replaceAll(replacement);
    }

    /**
     * 判断是否为空
     *
     * @param data 字符串
     * @return ‘空 true
     */
    public static boolean isEmpty(String data) {
        return data == null || data.length() < 1;
    }

    /**
     * 判字符串是否满足一定长度
     *
     * @param data 字符串
     * @param len  长度
     * @return 满足 false
     */
    public static boolean isEmpty(String data, int len) {
        boolean flag = isEmpty(data);
        return flag || !(data.length() == len);
    }

    /**
     * 判断是是否为空 可以判断长度
     *
     * @param data      字符串
     * @param minLength 最小长度
     * @param maxLength 最大长度
     * @return 是空或者 满足条件 返回true
     * @author jiangzeyin
     */
    public static boolean isEmpty(String data, int minLength, int maxLength) {
        // 对象 空
        if (data == null) {
            return true;
        }
        if (data.isEmpty()) {
            return true;
        }
        if (minLength <= 0 || maxLength <= 0) {
            throw new IllegalArgumentException(" minLength or maxLength <=0");
        }
        if (minLength > maxLength) {
            throw new IllegalArgumentException(" minLength > maxLength");
        }
        return data.length() > maxLength || data.length() < minLength;
    }


    public static String trimAll(String data) {
        if (isEmpty(data)) {
            return "";
        }
        return data.replaceAll("\\s*", "");
    }

    /**
     * 过滤&lt;, &gt;,\n 字符的方法。
     *
     * @param input 需要过滤的字符
     * @return 完成过滤以后的字符串
     */
    public static String filterHTML(String input) {
        if (input == null) {
            return null;
        }
        if (input.length() == 0) {
            return input;
        }
        input = input.trim();
        // input = input.replaceAll("　", "");
        // input = input.replaceAll("&", "&amp;");
        input = input.replaceAll("<", "&lt;");
        input = input.replaceAll(">", "&gt;");
        // input = input.replaceAll(" ", "&nbsp;");
        input = input.replaceAll("'", "&#39;");
        // input = input.replaceAll("\"", "&quot;");
        //input = input.replaceAll("\n", "<br>");

        // String s = "<:&lt;,>:&gt;, :&nbsp;,':&#39;,\":&quot;,\n:<br>";
        // StringBuffer sb = new StringBuffer(input);
        // String[] t = StringToArray(s, ",");
        // for (String string : t) {
        // String[] temp = string.split(":");
        // int i = sb.indexOf(temp[0]);
        // while (i > -1) {
        // int oldLen = temp[0].length();
        // int newLen = temp[1].length();
        // sb.delete(i, i + oldLen);
        // sb.insert(i, temp[1]);
        // i = sb.indexOf(temp[0], i + newLen);
        // }
        // }
        // return sb.toString();
        return input;
    }

    /**
     * 编译html
     *
     * @param input inp
     * @return str
     */
    public static String compileHtml(String input) {
        if (input == null) {
            return null;
        }
        if (input.length() == 0) {
            return input;
        }
        input = input.replaceAll("&amp;", "&");
        input = input.replaceAll("&lt;", "<");
        input = input.replaceAll("&gt;", ">");
        input = input.replaceAll("&nbsp;", " ");
        input = input.replaceAll("&#39;", "'");
        input = input.replaceAll("&quot;", "\"");
        return input.replaceAll("<br>", "\n");
    }

    /**
     * 将字符串按照空格拆分
     *
     * @param str 字符串
     * @return 数组
     */
    public static String[] stringToArray(String str) {
        return stringToArray(str, CONFIG_LOCATION_DELIMITERS);
    }

    /**
     * 将字符串按照空格拆分
     *
     * @param str       字符串
     * @param separator 指定字符
     * @return 数组
     */
    public static String[] stringToArray(String str, String separator) {
        if ((str == null) || (separator == null)) {
            return null;
        }

        int i = 0;
        StringTokenizer st = new StringTokenizer(str, separator);
        String[] array = new String[st.countTokens()];
        while (st.hasMoreTokens()) {
            array[(i++)] = st.nextToken();
        }
        return array;
    }

    public static ArrayList<String> stringToArrayList(String str, String separator) {
        ArrayList<String> arr = new ArrayList<>();
        if ((str == null) || (separator == null)) {
            return arr;
        }
        StringTokenizer st = new StringTokenizer(str, separator);
        while (st.hasMoreTokens()) {
            arr.add(st.nextToken());
        }
        return arr;
    }

    public static int[] stringToIntArray(String str, String separator) {
        if ((str == null) || (separator == null)) {
            return null;
        }

        int i = 0;
        StringTokenizer st = new StringTokenizer(str, separator);
        int[] array = new int[st.countTokens()];
        while (st.hasMoreTokens()) {
            array[(i++)] = parseInt(st.nextToken());
        }
        return array;
    }

    public static int parseInt(String num) {
        return parseInt(num, 0);
    }

    public static int parseInt(Object num) {
        if (num == null) {
            return 0;
        }
        return parseInt(num.toString(), 0);
    }

    public static int parseInt(Object obj, int default_) {
        return parseInt(convertNULL(obj), default_);
    }

    public static int parseInt(String num, int default_) {
        if ((num == null) || (num.length() == 0)) {
            return default_;
        }
        try {
            return Integer.parseInt(num);
        } catch (NumberFormatException ignored) {
        }
        return default_;
    }

    public static long parseLong(String num) {
        if (num == null) {
            return 0L;
        }
        try {
            return Long.parseLong(num);
        } catch (NumberFormatException ignored) {
        }
        return 0L;
    }

    public static float parseFloat(String num) {
        if (num == null) {
            return 0.0F;
        }
        try {
            return Float.parseFloat(num);
        } catch (NumberFormatException ignored) {
        }
        return 0.0F;
    }

    public static double parseDouble(String num) {
        if (num == null) {
            return 0.0D;
        }
        try {
            return Double.parseDouble(num);
        } catch (NumberFormatException ignored) {
        }
        return 0.0D;
    }

    public static String convertNULL(String input) {
        if (input == null) {
            return "";
        }
        return input.trim().intern();
    }

    public static String convertNULL(Object input) {
        if (input == null) {
            return "";
        }
        return convertNULL(input.toString());
    }

    /**
     * 转换异常信息
     *
     * @param e 异常
     * @return 字符串
     * @author jiangzeyin
     */
    public static String fromException(Throwable e) {
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            return "\r\n" + sw.toString() + "\r\n";
        } catch (Exception ignored) {
        }
        return "";
    }

    /**
     * 格式化路径
     *
     * @param input 字符串
     * @return 处理后
     */
    public static String clearPath(String input) {
        input = input.replace('\\', '/');
        return clearPath_(input);
    }

    /**
     * 格式化路径
     * 支持协议路径 ://
     *
     * @param input 字符串
     * @return 处理后
     */
    private static String clearPath_(String input) {
        int from = 0;
        int j = input.indexOf("://");
        if (j != -1) {
            from = j + 3;
        }
        int i = input.indexOf("//", from);
        if (i == -1) {
            return input;
        }

        String input_ = input.substring(0, i) + "/" + input.substring(i + 2);
        return clearPath_(input_);
    }

    /**
     * 驼峰命名
     *
     * @param inString 字符串
     * @return 结果
     */
    public static String captureName(String inString) {
        if (StringUtil.isEmpty(inString)) {
            return "";
        }
        if (inString.length() > 1) {
            return inString.substring(0, 1).toUpperCase() + inString.substring(1);
        }
        return inString.toUpperCase();
    }

    /**
     * 简化class name
     *
     * @param className className
     * @return 结果
     */
    public static String simplifyClassName(String className) {
        String[] packages = StringUtil.stringToArray(className, ".");
        if (packages == null || packages.length < 1) {
            return className;
        }
        int len = packages.length;
        if (len == 1) {
            return packages[0];
        }
        StringBuilder name = new StringBuilder();
        for (int i = 0; i < len - 1; i++) {
            String item = packages[i];
            name.append(item, 0, 1).append(".");
        }
        name.append(packages[len - 1]);
        return name.toString();
    }

    public static String join(Iterator iterator, CharSequence separator) {
        // handle null, zero and one elements before building a buffer
        if (iterator == null) {
            return null;
        }
        if (!iterator.hasNext()) {
            return "";
        }
        Object first = iterator.next();
        if (!iterator.hasNext()) {
            return first == null ? "" : first.toString();
        }
        // Java default is 16, probably too small
        // two or more elements
        StringBuilder buf = new StringBuilder(256);
        if (first != null) {
            buf.append(first);
        }

        while (iterator.hasNext()) {
            if (separator != null) {
                buf.append(separator);
            }
            Object obj = iterator.next();
            if (obj != null) {
                if (StringUtil.isEmpty(obj.toString())) {
                    continue;
                }
                buf.append(obj);
            }
        }
        return buf.toString();
    }

    public static String join(Collection collection, CharSequence separator) {
        if (collection == null) {
            return null;
        }
        return join(collection.iterator(), separator);
    }

    public static String join(Object[] collection, CharSequence separator) {
        if (collection == null) {
            return null;
        }
        return join(Arrays.asList(collection), separator);
    }

    public static String join(CharSequence separator, Object... collection) {
        if (collection == null) {
            return null;
        }
        return join(Arrays.asList(collection), separator);
    }
}
